
# os 模块提供了非常丰富的方法用来处理文件和目录.
import os, stat

# os.access(path, mode) 方法使用当前的uid/gid尝试访问路径,检验权限.
'''
path 要用来检测是否有访问权限的路径.
mode 测试存在的路径的模式
	os.F_OK: 测试path是否存在;
	os.R_OK: 测试path是否可读;
	os.W_OK: 测试path是否可写;
	os.X_OK: 测试path是否可执行.
'''
print(os.access("python.os", os.F_OK), end = ' ')
print(os.access("python.os", os.R_OK), end = ' ')
print(os.access("python.os", os.W_OK), end = ' ')
print(os.access("python.os", os.X_OK))
print()

# os.chdir() 方法用于改变当前工作目录到指定的路径.
print(os.chdir("../"))
print(os.chdir("runoob"))
print()

# os.chflags(path, flags) 方法用于设置路径的标记为数字标记.多个标记可以使用 OR 来组合起来.只支持在 Unix 下使用.
'''
path -- 文件名路径或目录路径.
flags -- 可以是以下值：
	stat.UF_NODUMP: 非转储文件
	stat.UF_IMMUTABLE: 文件是只读的
	stat.UF_APPEND: 文件只能追加内容
	stat.UF_NOUNLINK: 文件不可删除
	stat.UF_OPAQUE: 目录不透明,需要通过联合堆栈查看
	stat.SF_ARCHIVED: 可存档文件(超级用户可设)
	stat.SF_IMMUTABLE: 文件是只读的(超级用户可设)
	stat.SF_APPEND: 文件只能追加内容(超级用户可设)
	stat.SF_NOUNLINK: 文件不可删除(超级用户可设)
	stat.SF_SNAPSHOT: 快照文件(超级用户可设)
'''
#print(os.chflags("python.os", stat.UF_NOUNLINK))

# os.chmod(path, mode) 方法用于更改文件或目录的权限.
'''
path 文件名路径或目录路径.
flags 可用以下选项按位或操作生成;
	目录的读权限表示可以获取目录里文件名列表;
	执行权限表示可以把工作目录切换到此目录;
	删除添加目录里的文件必须同时有写和执行权限;
	文件权限以用户id->组id->其它顺序检验,最先匹配的允许或禁止权限被应用.
	stat.S_IXOTH: 其他用户有执行权0o001
	stat.S_IWOTH: 其他用户有写权限0o002
	stat.S_IROTH: 其他用户有读权限0o004
	stat.S_IRWXO: 其他用户有全部权限(权限掩码)0o007
	stat.S_IXGRP: 组用户有执行权限0o010
	stat.S_IWGRP: 组用户有写权限0o020
	stat.S_IRGRP: 组用户有读权限0o040
	stat.S_IRWXG: 组用户有全部权限(权限掩码)0o070
	stat.S_IXUSR: 拥有者具有执行权限0o100
	stat.S_IWUSR: 拥有者具有写权限0o200
	stat.S_IRUSR: 拥有者具有读权限0o400
	stat.S_IRWXU: 拥有者有全部权限(权限掩码)0o700
	stat.S_ISVTX: 目录里文件目录只有拥有者才可删除更改0o1000
	stat.S_ISGID: 执行此文件其进程有效组为文件所在组0o2000
	stat.S_ISUID: 执行此文件其进程有效用户为文件所有者0o4000
	stat.S_IREAD: windows下设为只读
	stat.S_IWRITE: windows下取消只读
'''
print(os.chmod("D:/MyCode/Python/runoob/python.os", stat.S_IREAD))
print(os.chmod("D:/MyCode/Python/runoob/python.os", stat.S_IWRITE))
print()

# os.chown(path, uid, gid) 方法用于更改文件所有者,如果不修改可以设置为 -1, 你需要超级用户权限来执行权限修改操作.只支持在 Unix 下使用.

# os.chroot(path) 方法用于更改当前进程的根目录为指定的目录,使用该函数需要管理员权限.

# os.close(fd) 方法用于关闭指定的文件描述符 fd.

# os.closerange(fd_low, fd_high) 方法用于关闭所有文件描述符 fd,从 fd_low (包含) 到 fd_high (不包含), 错误会忽略.
fd = os.open("python.os", os.O_RDONLY)
fdd = os.open("python-test-read.txt", os.O_RDONLY)
print(fd, fdd)
os.closerange(fd, fdd)
print()

# os.dup(fd) 方法用于复制文件描述符 fd.
# os.dup2(fd, fd2) 方法用于将一个文件描述符 fd 复制到另一个 fd2.

# os.fchdir(fd) 方法通过文件描述符改变当前工作目录.

# os.fchmod(fd, mode) 方法用于改变一个文件的访问权限,该文件由参数fd指定,参数mode是Unix下的文件访问权限.Unix上可用.
'''
mode 可以是以下一个或多个组成,多个使用 "|" 隔开：
	stat.S_ISUID: 设置 UID 位
	stat.S_ISGID: 设置组 ID 位
	stat.S_ENFMT: 系统文件锁定的执法行动
	stat.S_ISVTX: 在执行之后保存文字和图片
	stat.S_IREAD: 对于拥有者读的权限
	stat.S_IWRITE:对于拥有者写的权限
	stat.S_IEXEC: 对于拥有者执行的权限
	stat.S_IRWXU: 对于拥有者读、写、执行的权限
	stat.S_IRUSR: 对于拥有者读的权限
	stat.S_IWUSR: 对于拥有者写的权限
	stat.S_IXUSR: 对于拥有者执行的权限
	stat.S_IRWXG: 对于同组的人读写执行的权限
	stat.S_IRGRP: 对于同组读的权限
	stat.S_IWGRP: 对于同组写的权限
	stat.S_IXGRP: 对于同组执行的权限
	stat.S_IRWXO: 对于其他组读写执行的权限
	stat.S_IROTH: 对于其他组读的权限
	stat.S_IWOTH: 对于其他组写的权限
	stat.S_IXOTH: 对于其他组执行的权限
'''

# os.fchown(fd, uid, gid) 方法用于修改一个文件的所有权,这个函数修改一个文件的用户ID和用户组ID,该文件由文件描述符fd指定.Unix上可用.
# os.fdatasync(fd) 方法用于强制将文件写入磁盘,该文件由文件描述符fd指定,但是不强制更新文件的状态信息.如果你需要刷新缓冲区可以使用该方法.Unix上可用.

# os.fdopen(fd, [, mode[, bufsize]]) 方法用于通过文件描述符 fd 创建一个文件对象,并返回这个文件对象.Unix, Windows上可用.
'''
fd 打开的文件的描述符,在Unix下,描述符是一个小整数.
mode 可选,参数可以指定『r,w,a,r+,w+,a+,b』等.
bufsize 可选,指定返回的文件对象是否带缓冲.
	buffersize=0,表示没有带缓冲;
	bufsize=1,表示该文件对象是行缓冲的;
	bufsize=正数,表示使用一个指定大小的缓冲,单位为byte,但是这个大小不是精确的;
	bufsize=负数,表示使用一个系统默认大小的缓冲,对于tty字元设备一般是行缓冲,而对于其他文件则一般是全缓冲.
	如果这个参数没有指定,则使用系统默认的缓冲设定.
'''

# os.fpathconf(fd, name) 方法用于返回一个打开的文件的系统配置信息.Unix上可用.
'''
fd 打开的文件的描述符.
name 可选,参数可以指定『r,w,a,r+,w+,a+,b』等.
bufsize 检索的系统配置的值,也许是一个定义系统值的字符串,这些名字在很多标准中指定（POSIX.1, Unix 95, Unix 98, 和其它）.
	一些平台也定义了一些额外的名字.这些名字在主操作系统上pathconf_names的字典中.
	对于不在pathconf_names中的配置变量,传递一个数字作为名字,也是可以接受的.
'''

# os.fstat() 方法用于返回文件描述符fd的状态,类似 stat().Unix,Windows上可用.
'''
fstat 方法返回的结构:
	st_dev: 设备信息
	st_ino: 文件的i-node值
	st_mode: 文件信息的掩码,包含了文件的权限信息,文件的类型信息(是普通文件还是管道文件,或者是其他的文件类型)
	st_nlink: 硬连接数
	st_uid: 用户ID
	st_gid: 用户组 ID
	st_rdev: 设备 ID (如果指定文件)
	st_size: 文件大小,以byte为单位
	st_blksize: 系统 I/O 块大小
	st_blocks: 文件的是由多少个 512 byte 的块构成的
	st_atime: 文件最近的访问时间
	st_mtime: 文件最近的修改时间
	st_ctime: 文件状态信息的修改时间（不是文件内容的修改时间）
'''
fd = os.open("python.os", os.O_RDONLY)
print(os.fstat(fd))
os.close(fd)
print()

# os.fstatvfs() 方法用于返回包含文件描述符fd的文件的文件系统的信息,类似 statvfs().Unix上可用.
'''
fstatvfs 方法返回的结构:
	f_bsize: 文件系统块大小
	f_frsize: 分栈大小
	f_blocks: 文件系统数据块总数
	f_bfree: 可用块数
	f_bavail:非超级用户可获取的块数
	f_files: 文件结点总数
	f_ffree: 可用文件结点数
	f_favail: 非超级用户的可用文件结点数
	f_fsid: 文件系统标识 ID
	f_flag: 挂载标记
	f_namemax: 最大文件长度
'''

# os.fsync() 方法强制将文件描述符为fd的文件写入硬盘.在Unix, 将调用fsync()函数; 在Windows, 调用 _commit()函数.在Unix,Windows中有效.
# 文件对象f,f.flush() 刷新缓冲区,将缓冲区中的数据立刻写入文件,同时清空缓冲区, 然后os.fsync(f.fileno()), 确保与f相关的所有内容都写入了硬盘.
fd = os.open("python.os", os.O_RDWR)
print("open:", os.read(fd, 100))
os.lseek(fd, 0, 2)
os.write(fd, bytes(str(os.fstat(fd).st_mtime)+'\n', encoding = 'utf-8'))
os.lseek(fd, 0, 0)
print("write:", os.read(fd, 100))
os.fsync(fd)
os.lseek(fd, 0, 0)
print("fsync:", os.read(fd, 100))
os.close(fd)
